package com.ruoyi.web.schedule;

import com.ruoyi.common.customize.redis.constants.CommonRedisConstants;
import com.ruoyi.common.customize.redis.utils.RedisUtils;
import com.ruoyi.framework.web.exception.TadpoleException;
import com.ruoyi.web.domain.VipDepositDetail;
import com.ruoyi.web.enums.VipDepositDetailEnum;
import com.ruoyi.web.mapper.UserCapitalMapper;
import com.ruoyi.web.mapper.VipDepositDetailMapper;
import com.ruoyi.web.utils.MysqlUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 每日0点10分处理到期的vip押金明细
 *
 * @since 2023/3/27 15:51
 */
@Slf4j
@Component
@EnableScheduling
@AllArgsConstructor
public class VipDepositDetailTask {

    private final VipDepositDetailMapper vipDepositDetailMapper;
    private final UserCapitalMapper userCapitalMapper;
    private final MysqlUtil mysqlUtil;
    private final RedisUtils redisUtils;

    @Scheduled(cron = "0 10 0 * * ?")
    public void task() {
        RLock lock = redisUtils.getLock(CommonRedisConstants.VIP_DEPOSIT_DETAIL_CHECK_EXPIRE, null);
        if (Objects.isNull(lock)) {
            return;
        }

        try {
            long l1 = System.currentTimeMillis();
            log.error("处理到期的vip押金明细--开始");
            // 每次处理100条
            Date now = new Date();

            // 有需要处理的数据，每次查询1000条
            VipDepositDetail condition = new VipDepositDetail();
            condition.setUpdateTime(now);
            List<Long> idList;
            while (!CollectionUtils.isEmpty((idList = vipDepositDetailMapper.selectExpireList(now)))) {
                // 遍历处理数据
                idList.forEach(id -> {
                    try {
                        mysqlUtil.startLocalTx();
                        condition.setId(id);
                        handle(condition);
                        mysqlUtil.commitLocalTx();
                    } catch (Throwable e) {
                        mysqlUtil.rollbackLocalTx();
                        log.error("处理到期的vip押金明细--失败，id：{}，原因：{}", id, e.getMessage());
                        e.printStackTrace();
                    }
                });
            }

            log.error("处理到期的vip押金明细--完成，耗时：{} 毫秒", System.currentTimeMillis() - l1);

        } finally {
            redisUtils.releaseLock(lock);
        }
    }

    /**
     * 处理数据
     *
     * @param detail 数据
     * @since 2023/3/27 16:03
     */
    private void handle(VipDepositDetail detail) {
        detail = vipDepositDetailMapper.getOneLock(detail);
        if (Objects.isNull(detail)
                || !VipDepositDetailEnum.Status.CAN_NOT.getValue().equals(detail.getStatus())) {
            return;
        }

        detail.setStatus(VipDepositDetailEnum.Status.CAN.getValue());
        // 修改明细状态
        if (vipDepositDetailMapper.updateVipDepositDetail(detail) != 1) {
            throw new TadpoleException();
        }

        // 修改资金账户
        if (userCapitalMapper.minusVipDeposit(detail.getUserId(), detail.getAmount()) != 1) {
            throw new TadpoleException("减少VIP押金失败");
        }
        if (userCapitalMapper.addBalance(detail.getUserId(), detail.getAmount()) != 1) {
            throw new TadpoleException("增加余额失败");
        }
    }
}
